<!--
@Description:表单容器
@Author:zqy
@Date:2022-08-19 11:15:16
@Last Modified by:zqy
@Last Modified time:2022-08-19 11:15:16
 -->
<script>
/** deep copy
 * @param {Array|Object} source
 * @returns {Array|Object}
 */
function deepCopy(source) {
  let target
  if (isType(source, 'Array')) {
    target = []
    for (const e of source) {
      target.push(deepCopy(e))
    }
  } else if (isType(source, 'Object')) {
    target = {}
    for (const key of Object.keys(source)) {
      target[key] = deepCopy(source[key])
    }
  } else {
    return source
  }
  return target
}

const pickerOptionsDateTimeRange = {
  shortcuts: [{
    text: '最近一周',
    onClick(picker) {
      const end = new Date()
      const start = new Date()
      start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
      picker.$emit('pick', [start, end])
    }
  }, {
    text: '最近一个月',
    onClick(picker) {
      const end = new Date()
      const start = new Date()
      start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
      picker.$emit('pick', [start, end])
    }
  }, {
    text: '最近三个月',
    onClick(picker) {
      const end = new Date()
      const start = new Date()
      start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
      picker.$emit('pick', [start, end])
    }
  }]
}
// 根据日期算
const pickerOptionsDateRange = {
  shortcuts: [{
    text: '最近一周',
    onClick(picker) {
      const end = new Date(getYMDDate(new Date()))
      const start = new Date(getYMDDate(new Date()))
      start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
      picker.$emit('pick', [start, end])
    }
  }, {
    text: '最近一个月',
    onClick(picker) {
      const end = new Date(getYMDDate(new Date()))
      const start = new Date(getYMDDate(new Date()))
      start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
      picker.$emit('pick', [start, end])
    }
  }, {
    text: '最近三个月',
    onClick(picker) {
      const end = new Date(getYMDDate(new Date()))
      const start = new Date(getYMDDate(new Date()))
      start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
      picker.$emit('pick', [start, end])
    }
  }]
}
const pickerOptionsDateTime = {
  disabledDate(time) {
    return time.getTime() > Date.now()
  },
  shortcuts: [{
    text: '今天',
    onClick(picker) {
      picker.$emit('pick', new Date())
    }
  }, {
    text: '昨天',
    onClick(picker) {
      const date = new Date()
      date.setTime(date.getTime() - 3600 * 1000 * 24)
      picker.$emit('pick', date)
    }
  }, {
    text: '一周前',
    onClick(picker) {
      const date = new Date()
      date.setTime(date.getTime() - 3600 * 1000 * 24 * 7)
      picker.$emit('pick', date)
    }
  }]
}
// 年月日
function getYMDDate(d) {
  return new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime()
}
// 设置日期禁用状态
/** @description 设置日期禁用状态
 * @param {Date} d 限制日期
 * @param {String} operator 操作 =禁用当前日期, < 禁用小于d的日期，>禁用大于d的日期，<= 禁用小于等于d的日期，>=禁用大于等于d的日期
 */
function disabledDate(d, operator = '') {
  if (d) {
    d = getYMDDate(d)
  }
  return function(date) {
    if (operator === '') {
      return false
    }
    if (operator === '=' && d === getYMDDate(date)) {
      return true
    }
    if (operator === '<=' && getYMDDate(date) <= d) {
      return true
    }
    if (operator === '>=' && getYMDDate(date) >= d) {
      return true
    }
    if (operator === '<' && getYMDDate(date) < d) {
      return true
    }
    if (operator === '>' && getYMDDate(date) > d) {
      return true
    }
    return false
  }
}
export default {
  name: 'QupFormContainer',
  abstract: true,
  props: {
    column: {
      type: Number,
      default: 4
    },
    gutter: {
      type: Number,
      default: 0
    },
    disabled: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      visible: false
    }
  },
  render(h) {
    const vnode = this.$scopedSlots.default()[0]
    if ( !vnode.componentOptions.tag || vnode.componentOptions.tag !== 'el-form' ) {
      console.error('子组件不是el-form')
      return h('span', '子组件不是el-form')
    }
    // 收集必选项
    const requireList = []
    const rules = vnode.componentOptions.propsData.rules || {}
    for (const key of Object.keys(rules)) {
      let r = rules[key]
      if (!(r instanceof Array)) {
        r = [r]
      }
      for (const item of r) {
        if (item.required) {
          requireList.push(key)
          break
        }
      }
    }
    // const span = Math.floor(24 / this.column)
    const span = 24 / this.column
    // const items = []
    const children = vnode.componentOptions.children || []
    let setMore = false // 之后的form-item隐藏
    for (let i = 0; i < children.length; i++) {
      const n = children[i]
      if (!n.componentOptions) {
        continue
      }
      if (n.componentOptions.tag === 'el-form-item') {
        if (n.componentOptions.children) {
          // for (const c of n.componentOptions.children) {
          for (let j = 0; j < n.componentOptions.children.length; j++) {
            const c = n.componentOptions.children[j]
            if (!c.componentOptions) {
              continue
            }
            // 如果disabled为true则禁用
            if (this.disabled) {
              if (c.componentOptions.tag !== 'SearchSelectPicker') {
                c.componentOptions.propsData.disabled = this.disabled
                if (!c.data.attrs) {
                  c.data.attrs = {}
                }
                c.data.attrs.disabled = this.disabled
              } else if (c.componentOptions.tag === 'SearchSelectPicker') {
                c.componentOptions.propsData.sspDisabled = this.disabled
              }
            }
            // 设置el-seclect样式
            if (c.componentOptions.tag === 'el-select') {
              c.componentOptions.listeners ? '' : c.componentOptions.listeners = {}
              c.componentOptions.listeners['hook:mounted'] = function() {
                c.componentInstance.$on('visible-change', function(v) {
                  try {
                    if (!v)c.componentInstance.blur()
                    // 使远程搜索框可以选择
                    if (v && !this.multiple) {
                      if (this.value !== '') {
                        this.selectedLabel = this.currentPlaceholder
                      } else if (this.query !== '') {
                        this.selectedLabel = this.query
                      }
                    }
                  } catch (error) {
                    console.log(error)
                  }
                })
              }
              c.data.staticStyle = Object.assign(c.data.staticStyle || {}, {
                width: '100%'
              })
            } else if (c.componentOptions.tag === 'el-date-picker') {
              c.data.staticStyle = Object.assign(c.data.staticStyle || {}, {
                width: '100%'
              })
              // 如果el-date-picker上带有opt参数，则自动加上pickerOptions选项
              if (c.data.attrs && ('opt' in c.data.attrs)) {
                c.componentOptions.propsData ? '' : c.componentOptions.propsData = {}
                if (c.componentOptions.propsData.type === 'datetimerange') {
                  c.componentOptions.propsData['pickerOptions'] = deepCopy(pickerOptionsDateTimeRange)
                } else if (c.componentOptions.propsData.type === 'datetime') {
                  c.componentOptions.propsData['pickerOptions'] = deepCopy(pickerOptionsDateTime)
                } else if (c.componentOptions.propsData.type === 'daterange') {
                  c.componentOptions.propsData['pickerOptions'] = deepCopy(pickerOptionsDateRange)
                }
              }
              // 如果el-date-picker上带有operator, limite参数，则自动加上disabledDate选项
              // disabledDate
              if (c.data.attrs && ('operator' in c.data.attrs) && ('limite' in c.data.attrs)) {
                c.componentOptions.propsData ? '' : c.componentOptions.propsData = {}
                c.componentOptions.propsData['pickerOptions'] ? '' : c.componentOptions.propsData['pickerOptions'] = {}
                // disabledDate
                const limite = c.data.attrs.limite
                const operator = c.data.attrs.operator
                c.componentOptions.propsData['pickerOptions']['disabledDate'] = disabledDate(limite, operator)
              }
            } else if (c.componentOptions.tag === 'el-input-number') {
              c.data.staticStyle = Object.assign(c.data.staticStyle || {}, {
                width: '100%'
              })
            } else if (c.componentOptions.tag === 'el-input') {
              c.componentOptions.propsData ? '' : c.componentOptions.propsData = {}
              // 如果el-input上面带有number参数则，监听change时间
              if ('number' in c.data.attrs) {
                c.componentOptions.listeners ? '' : c.componentOptions.listeners = {}
                c.componentOptions.listeners['hook:mounted'] = function() {
                  c.componentInstance.$on('change', function(v) {
                    c.componentInstance.$emit('input', v.toString().replace(/[^\d.]/g, ''))
                  })
                }
              }
              // 如果设置了type='textarea' maxlength 则限制输入数量，show是否显示提示
              const inputType = c.componentOptions.propsData.type
              if (inputType === 'textarea' || inputType === 'text' || !inputType) {
                if ('maxlength' in c.data.attrs) {
                  // c.componentOptions.listeners ? '' : c.componentOptions.listeners = {}
                  // c.componentOptions.listeners['hook:mounted'] = function() {
                  //   c.componentInstance.$on('change', function(v) {
                  //     c.componentInstance.$emit('input', v.slice(0, c.data.attrs.maxlength))
                  //   })
                  // }
                  try {
                    const prop = n.componentOptions.propsData['prop']
                    let contentRules = vnode.componentOptions.propsData['rules'][prop]
                    if (!contentRules) {
                      contentRules = []
                      vnode.componentOptions.propsData['rules'][prop] = contentRules
                    }
                    // 检测是否已添加，防止死循环
                    let t = true
                    for (const item of contentRules) {
                      if (item.id) {
                        t = false
                        break
                      }
                    }
                    if (t) {
                      vnode.componentOptions.propsData['rules'][prop].push({
                        // required: true,
                        validator: (r, v, cb) => {
                          if (v === undefined || v === null) {
                            v = ''
                          }
                          if (v.length <= c.data.attrs.maxlength) {
                            cb()
                          } else {
                            cb(new Error(`至多能输入${c.data.attrs.maxlength}字`))
                          }
                        },
                        trigger: 'change',
                        id: true
                      })
                    }
                  } catch (error) {
                    console.log(error)
                  }
                }
                if ('tip' in c.data.attrs && 'maxlength' in c.data.attrs) {
                  const first = n.componentOptions.children.slice(0, j + 1)
                  let last = []
                  if (j < n.componentOptions.children.length - 1) {
                    last = n.componentOptions.children.slice(j + 1)
                  }
                  // 添加提示
                  let t = 0
                  try {
                    t = c.data.attrs.maxlength - c.componentOptions.propsData.value.length
                  } catch (error) {
                    console.log(error)
                  }
                  const tip = h('span', {
                    class: 'input-tip'
                  }, [
                    '还能输入',
                    h('span', t > 0 ? t : 0),
                    '字'
                  ])
                  first.push(tip)
                  n.componentOptions.children = [...first, ...last]
                }
              }
            }
          }
        }
        n.data.style = n.data.style || {}
        n.data.attrs = n.data.attrs || {}
        // 如果el-form-item上设置了span则使用该span
        if (n.data.attrs && n.data.attrs.hasOwnProperty('span')) {
          n.data.style = Object.assign(n.data.style, {
            flex: `0 0 ${n.data.attrs.span * 100 / 24}%`
          })
          // items.push(h('el-col', { props: { span: n.data.attrs.span }}, [n]))
        } else {
          n.data.style = Object.assign(n.data.style, {
            flex: `0 0 ${span * 100 / 24}%`
          })
          // items.push(h('el-col', { props: { span }}, [n]))
        }
        // 更多按钮
        if ('hidden' in n.data.attrs) {
          setMore = true
        }
        if (setMore && !('show' in n.data.attrs) && !requireList.includes(n.componentOptions.propsData.prop)) {
          n.data.staticClass = 'hidden'
        }
        // 添加更多按钮
        if (setMore && 'more' in n.data.attrs) {
          n.data.style.flex = n.data.style.flex.replace(/^0/, '1')
          n.componentOptions.children.unshift(
            h('el-button', {
              attrs: {
                flag: 'more',
                size:'mini'
              },
              on: {
                click: () => {
                  this.visible = !this.visible
                  for (const c of this._vnode.componentInstance.$children) {
                    const el = c.$el
                    if (el.classList.contains('hidden') && this.visible) {
                      el.style.display = 'block'
                    }
                    if (el.classList.contains('hidden') && !this.visible) {
                      el.style.display = 'none'
                    }
                    if ('more' in c.$attrs) {
                      const span = c.$el.querySelector('button[flag="more"]:first-child>span>span')
                      const i = c.$el.querySelector('button[flag="more"]:first-child>span>i')
                      if (this.visible) {
                        span.innerText = '收起'
                        i.className='el-icon-arrow-up'
                      } else {
                        span.innerText = '更多'
                        i.className='el-icon-arrow-down'
                      }
                    }
                  }
                }
              }
            }, [h('span','更多'),h('i',{class:'el-icon-arrow-down'},'')])
          )
        }
      }
    }
    vnode.data.staticClass = 'formContainer'
    // vnode.componentOptions.children = [h('el-row', { props: { type: 'flex', gutter: this.gutter }, style: { flexWrap: 'wrap' }}, items)]
    return vnode
  }
}
</script>
<style lang="scss">
  .formContainer{
    display: flex;
    flex-wrap: wrap;
  }
  .hidden{
    display: none;
  }
</style>
